package com.charactereducatio.order.service;

import com.charactereducation.module.vo.*;
import com.charactereducation.tools.GenerateID;
import com.charactereducation.tools.HttpClientHelper;
import com.charactereducation.tools.MD5Tools;
import com.charactereducation.tools.XmlAnalysisTools;
import com.charactereducation.tools.def.FixedData;
import com.charactereducation.tools.myRunTime.MyRunTimeExcption;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Baggio on 2017/2/16.
 */
@Primary
@Service("weChatPayService")
public class WeChatPayServiceImpl extends PayBase implements PayService {
    @Autowired
    private WeChatPaymentFeedbackService weChatPaymentFeedbackService;

    @Autowired
    private WeChatOrderFeedbackService weChatOrderFeedbackService;

    @Autowired
    private OrderService orderService;

    @Override
    public PayParameter pay(String orderId, String price, String remoteAddr, Map<String,String> payParametersMap) throws Exception {

        List<WeChatPaymentFeedback> paymentFeedbacksList = weChatPaymentFeedbackService
                .findWeChatPaymentFeedbackByOutTradeNo(orderId);

        if (!paymentFeedbacksList.isEmpty()) {
            throw new MyRunTimeExcption("【订单已经生成过了。。。。。。。】");
        }

        Order order = orderService.getOrderById(Long.parseLong(orderId));

        PayParameter payParameter = new PayParameter();
        Map<String, String> parameterMap = new HashMap<String, String>();
        parameterMap.put("appid", FixedData.ENTERPRISE_APP_ID);
        parameterMap.put("mch_id", FixedData.MERCHANT_NUMBER);
        parameterMap.put("nonce_str", GenerateID.getRandomNum(32, false));
         parameterMap.put("body", this.getProductName(orderId));
        parameterMap.put("out_trade_no", orderId);
        parameterMap.put("total_fee", price);
        parameterMap.put("spbill_create_ip", remoteAddr);
        parameterMap.put("notify_url", FixedData.ASYNCHRONOUS_RECEPTION);         // 微信异步反馈下订单结果信息的地址
        parameterMap.put("trade_type", "NATIVE");   // 为此值时才有二维码地址返回

        // 字段组合并字典排序最后MD5加密
        String sign_tmp = WeChatNotification.dictionarySorting(parameterMap) + "&key=" + FixedData.WX_KEY;
        String sign = MD5Tools.MD5(sign_tmp).toUpperCase();
        parameterMap.put("sign", sign);
        logger.warn("【组装后的字典排序sign_tmp：" + sign_tmp + "】。。。。。。");
        logger.warn("【最后生成的加密字段sign：" + sign + "】。。。。。。");

        try {
            String requestString = XmlAnalysisTools.stringToWxForXML(parameterMap);
            String dataString = HttpClientHelper.stringPost(FixedData.CREATE_ORDER_URL, requestString);
            Map<String, String> resultMap = XmlAnalysisTools.getResultMap(dataString);
            logger.info("【下单xml请求字符串：" + requestString + "】。。。。。。");
            logger.warn("【下单结果回调参数内容体：" + dataString + "】。。。。。。");

            if (null == resultMap) {
                logger.warn("【XML解析错误。。。。。。】");
                throw new MyRunTimeExcption("【XML解析错误。。。。。。】");
            }

            String returnCode = resultMap.get("return_code");
            String resultCode = resultMap.get("result_code");
            String errCode = resultMap.get("err_code");
            String wxSign = resultMap.get("sign");

            if ("FAIL".equals(returnCode)) {
                logger.warn("【下单请求失败。。。。。。】");
                String errorMessage = WeChatNotification.getMessage(errCode);
                logger.warn("【"+ errCode + "：" + errorMessage+"】");
                logger.warn(errorMessage);
                throw new MyRunTimeExcption(errorMessage);
            }
            if ("FAIL".equals(resultCode)) {
                logger.warn("【下订单失败。。。。。。】");
                String errorMessage = resultMap.get("err_code_des");
                logger.warn("【"+ errCode + "：" + errorMessage+"】");
                throw new MyRunTimeExcption(errorMessage);
            }
            if ("SUCCESS".equals(returnCode) && "SUCCESS".equals(resultCode)) {

                String localWxSignTemp = WeChatNotification.dictionarySortingWxFeedBack(resultMap);
                logger.info("localWxSignTemp===>"+localWxSignTemp);
                String localWxSign = MD5Tools.MD5(localWxSignTemp + "&key=" + FixedData.WX_KEY).toUpperCase();

                if (null == wxSign || !wxSign.equals(localWxSign)) {
                    logger.warn("【本地得出反馈签名：" + localWxSign + "】。。。。。。");
                    logger.warn("【微信得出反馈签名：" + wxSign + "】。。。。。。");
                    logger.warn("【微信反馈签名和本地签名不一致。。。。。。】");
                    throw new MyRunTimeExcption("【微信反馈签名和本地签名不一致。。。。。。】");
                } else {
                    logger.warn("【订单请求成功。。。。。。】");
                    logger.warn("【本地得出反馈签名：" + localWxSign + "】。。。。。。");
                    logger.warn("【微信得出反馈签名：" + wxSign + "】。。。。。。");
                    logger.warn("【二维码地址为：" + resultMap.get("code_url") + "】。。。。。。");

                    // 创建微信订单信息
                    WeChatOrderFeedback weChatOrderFeedback = WeChatNotification
                            .InjectedObj(new WeChatOrderFeedback(), resultMap, true);
                    weChatOrderFeedback.setOrderFeedbackId(GenerateID.CreatetID());
                    weChatOrderFeedback.setOrderId(orderId);
                    weChatOrderFeedback.setCreateTime(new Date());
                    weChatOrderFeedbackService.createWeChatOrderFeedback(weChatOrderFeedback);

                    // 为返回二维码页面准备相应信息
                    String codeUrl = resultMap.get("code_url");
                    Map<String, String> returnMap = new HashMap<String, String>();
                    returnMap.put("orderFeedbackId", new String(weChatOrderFeedback.getOrderFeedbackId().toString()));
                    returnMap.put("price", price);
                    returnMap.put("codeUrl", codeUrl);
                    returnMap.put("orderId", orderId);
                    returnMap.put("customerId", String.valueOf(order.getUserId().longValue()));
                    payParameter.setMap(returnMap);
                    payParameter.setBankUrl("/wechat_pay/topay");

                    return payParameter;
                }
            } else {
                logger.warn("【系统请求失败。。。。。。】");
                throw new MyRunTimeExcption("【系统请求失败。。。。。。】");
            }
        } catch (MyRunTimeExcption e) {
            logger.warn("【" + e.getMessage() + "。。。。。。】");
            throw new MyRunTimeExcption(e.getMessage());
        }

    }

    @Override
    public Map<String, String> notification(Map<String, String> map) {
        logger.info("【微信支付回调。。。。。。】");
        // 从XML获取成MAP对象
        String xml = map.get("xml");
        Map<String, String> resultMap = XmlAnalysisTools.getResultMap(xml);
        if(null == resultMap) {
            logger.warn("【XML解析错误。。。。。。】");
            throw new MyRunTimeExcption("【XML解析错误。。。。。。】");
        }

        String errCode = resultMap.get("err_code");
        String orderId = resultMap.get("out_trade_no");
        String returnCode = resultMap.get("return_code");
        String resultCode = resultMap.get("result_code");
        String acqSeqId = resultMap.get("transaction_id");

        // 检测反馈状况
        if ("FAIL".equals(returnCode)) {
            logger.warn("【用户支付后反馈请求失败。。。。。。】");
            String errorMessage = WeChatNotification.getMessage(errCode);
            logger.warn(errorMessage);
            throw new MyRunTimeExcption(errorMessage);
        }
        if ("FAIL".equals(resultCode)) {
            logger.warn("【支付订单业务失败。。。。。。】");
            String errorMessage = resultMap.get("err_code_des");
            logger.warn("【"+errorMessage+"】。。。。。。");
            throw new MyRunTimeExcption(errorMessage);
        }
        if ("SUCCESS".equals(returnCode) && "SUCCESS".equals(resultCode)) {

            // 支付成功后处理逻辑
            logger.warn("【订单请求成功。。。。。。】");
            payin(Long.parseLong(orderId), acqSeqId);
            List<WeChatPaymentFeedback> list = weChatPaymentFeedbackService
                    .findWeChatPaymentFeedbackByOutTradeNo(orderId);

            if (null == list || list.isEmpty()) {
                WeChatPaymentFeedback weChatPaymentFeedback;

                try {
                    weChatPaymentFeedback = WeChatNotification.InjectedObj(new WeChatPaymentFeedback(), resultMap, true);
                    weChatPaymentFeedback.setCreateTime(new Date());
                    
                } catch (IllegalAccessException e) {
                    logger.warn(e.getMessage());
                    throw new MyRunTimeExcption(e);
                } catch (InstantiationException e) {
                    logger.warn(e.getMessage());
                    throw new MyRunTimeExcption(e);
                }

                weChatPaymentFeedbackService.createWeChatPaymentFeedback(weChatPaymentFeedback);
            }
        } else {
            logger.warn("支付反馈失败。。。。。。");
            throw new MyRunTimeExcption("支付反馈失败。。。。。。");
        }

        Map<String, String> returnMap = new HashMap<String, String>();
        returnMap.put("return_code", "SUCCESS");
        returnMap.put("return_msg", "OK");
        String ResultXml = XmlAnalysisTools.resultData(returnMap);

        returnMap.put("xml", ResultXml);
        return returnMap;
    }

    @Override
    public PayParameter refund(Order order, Integer price) {
        return null;
    }

    public Map<String, String> queryWxOrder(String orderId) {

        Map<String, String> parameterMap = new HashMap<String, String>();
        parameterMap.put("appid", FixedData.ENTERPRISE_APP_ID);
        parameterMap.put("mch_id", FixedData.MERCHANT_NUMBER);
        parameterMap.put("out_trade_no", orderId);
        parameterMap.put("nonce_str", GenerateID.getRandomNum(32, false));
        parameterMap.put("sign_type", "MD5");

        String sign_tmp = WeChatNotification.dictionarySorting(parameterMap) + "&key=" + FixedData.WX_KEY;
        String sign = MD5Tools.MD5(sign_tmp).toUpperCase();
        parameterMap.put("sign", sign);
        logger.warn("【微信订单查询请求参数的sign_tmp：" + sign_tmp + "】。。。。。。");
        logger.warn("【微信订单查询请求参数的sign：" + sign + "】。。。。。。");

        String requestString = XmlAnalysisTools.stringToWxForXML(parameterMap);
        String dataString = HttpClientHelper.stringPost(FixedData.QUERY_ORDER_URL, requestString);
        Map<String, String> resultMap = XmlAnalysisTools.getResultMap(dataString);
        logger.warn("【微信查询xml请求字符串：" + requestString + "】。。。。。。");
        logger.warn("【微信查询结果回调参数内容体：" + dataString + "】。。。。。。");

        if (null == resultMap) {
            logger.warn("【XML解析错误。。。。。。】");
            throw new MyRunTimeExcption("【XML解析错误。。。。。。】");
        }

        String returnCode = resultMap.get("return_code");
        String resultCode = resultMap.get("result_code");
        String tradeState = resultMap.get("trade_state");
        String tradeStateDesc = resultMap.get("trade_state_desc");
        String errCode = resultMap.get("err_code");
        String errCodeDes = resultMap.get("err_code_des");

        Map<String, String> paymentResult = new HashMap<String, String>();

        if ("FAIL".equals(resultCode)) {
            logger.warn("【" + errCode + "：" + errCodeDes + "】。。。。。。");
            paymentResult.put("resultMsg", errCodeDes);
            paymentResult.put("resultCode", "-1");
            return paymentResult;
        }
        if ("REFUND".equals(tradeState)
                || "CLOSED".equals(tradeState)
                || "REVOKED".equals(tradeState)
                || "USERPAYING".equals(tradeState)
                || "PAYERROR".equals(tradeState)) {
            logger.warn("【" + tradeState + "：" + tradeStateDesc + "】。。。。。。");
            paymentResult.put("resultMsg", tradeStateDesc);
            paymentResult.put("resultCode", "-1");
            return paymentResult;
        }
        if ("NOTPAY".equals(tradeState)) {
            logger.warn("【" + tradeState + "：" + tradeStateDesc + "】。。。。。。");
            paymentResult.put("resultMsg", tradeStateDesc);
            paymentResult.put("resultCode", "0");
            return paymentResult;
        }
        if ("SUCCESS".equals(tradeState)) {
            logger.warn("【" + tradeState + "：" + tradeStateDesc + "】。。。。。。");
            paymentResult.put("resultMsg", tradeStateDesc);
            paymentResult.put("resultCode", "1");
            return paymentResult;
        } else {
            logger.warn("【未知的支付状态】。。。。。。");
            paymentResult.put("resultMsg", "未知的支付状态");
            paymentResult.put("resultCode", "-1");
            return paymentResult;
        }

    }

}
